Roberto Soares - LfLngLrnng
in/roberto-dos-santos-soares
Portifólio: roberto-ssoares
PoD Academy - Prof. Bruno Jardim
[+] Faturamento,
[-] Custo,
[+] Qualidade de vida
CRISP-DM (Modeling) | Desenvolvimento de Modelos
Modelos Supervisionados - Problemas de Classificação
Instalando e Carregando Pacotes
#!pip install -q -U watermark
#!pip install -q -U lightgbm
#!pip install -q -U xgboost
#!pip install -q -U catboost
#!pip install -q -U scipy
#!conda install -q anaconda::scipy
Importando Bibliotecas:
import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import itertools
import lightgbm as lgb
import xgboost as xgb
import pickle
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, roc_curve, precision_recall_curve, roc_auc_score, auc
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
from sklearn.model_selection import GridSearchCV
from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import GradientBoostingClassifier
from catboost import CatBoostClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.neural_network import MLPClassifier
from sklearn.svm import SVC
from sklearn.ensemble import StackingClassifier
from sklearn.preprocessing import label_binarize
#from scipy import interp
from itertools import cycle
interp = np.interp
import warnings
warnings.filterwarnings('ignore')
%matplotlib inline
matplotlib.rcParams['font.size'] = 10
matplotlib.rcParams['figure.figsize'] = (12, 6)
#matplotlib.rcParams['figure.facecolor'] = '#00000000'
#pd.options.display.max_columns = 20
#pd.options.display.max_rows = 20
#pd.options.display.max_colwidth = 80
np.set_printoptions(precision=4, suppress=True)
# Versões dos pacotes usados neste jupyter notebook
%reload_ext watermark
%watermark -a "Roberto Soares - LfLngLrnng"
Author: Roberto Soares - LfLngLrnng
Função de Cálculo da Estatística do KS
calcular_ks_statistic()
return ks_statistic
Em resumo, a função calcula a estatística KS comparando as distribuições cumulativas de eventos e não eventos, fornecendo uma medida do poder discriminatório do modelo de classificação.
import numpy as np
import pandas as pd
from sklearn.metrics import confusion_matrix, roc_curve, precision_recall_curve, roc_auc_score
import itertools
import matplotlib.pyplot as plt
def calcular_ks_statistic(y_true, y_score):
df = pd.DataFrame({'score': y_score, 'target': y_true})
df = df.sort_values(by='score', ascending=False)
total_events = df.target.sum()
total_non_events = len(df) - total_events
df['cum_events'] = df.target.cumsum()
df['cum_non_events'] = (df.target == 0).cumsum()
df['cum_events_percent'] = df.cum_events / total_events
df['cum_non_events_percent'] = df.cum_non_events / total_non_events
ks_statistic = np.abs(df.cum_events_percent - df.cum_non_events_percent).max()
return ks_statistic
def avaliar_modelo(X_train, y_train, X_test, y_test, modelo, nm_modelo):
feature_names = list(X_train.columns)
# Criação da figura e dos eixos
fig, axs = plt.subplots(5, 2, figsize=(15, 30)) # Ajustado para incluir novos gráficos
plt.tight_layout(pad=6.0)
# Cor azul claro
cor = 'skyblue'
# Taxa de Evento e Não Evento
event_rate = np.mean(y_train)
non_event_rate = 1 - event_rate
axs[0, 0].bar(['Evento', 'Não Evento'], [event_rate, non_event_rate], color=[cor, 'lightcoral'])
axs[0, 0].set_title('Taxa de Evento e Não Evento')
axs[0, 0].set_ylabel('Proporção')
# Importância dos Atributos
importancias = None
if hasattr(modelo, 'coef_'):
importancias = np.abs(modelo.coef_[0])
elif hasattr(modelo, 'feature_importances_'):
importancias = modelo.feature_importances_
if importancias is not None:
importancias_df = pd.DataFrame({'feature': feature_names, 'importance': importancias})
importancias_df = importancias_df.sort_values(by='importance', ascending=True)
axs[0, 1].barh(importancias_df['feature'], importancias_df['importance'], color=cor)
axs[0, 1].set_title('Importância das Variáveis - ' + nm_modelo)
axs[0, 1].set_xlabel('Importância')
else:
axs[0, 1].axis('off') # Desativa o subplot se não houver importâncias para mostrar
# Confusion Matrix - Treino
y_pred_train = modelo.predict(X_train)
cm_train = confusion_matrix(y_train, y_pred_train)
axs[1, 0].imshow(cm_train, interpolation='nearest', cmap=plt.cm.Blues)
axs[1, 0].set_title('Confusion Matrix - Treino - ' + nm_modelo)
axs[1, 0].set_xticks([0, 1])
axs[1, 0].set_yticks([0, 1])
axs[1, 0].set_xticklabels(['0', '1'])
axs[1, 0].set_yticklabels(['0', '1'])
thresh = cm_train.max() / 2.
for i, j in itertools.product(range(cm_train.shape[0]), range(cm_train.shape[1])):
axs[1, 0].text(j, i, format(cm_train[i, j], 'd'),
horizontalalignment="center",
color="white" if cm_train[i, j] > thresh else "black")
# Confusion Matrix - Teste
y_pred_test = modelo.predict(X_test)
cm_test = confusion_matrix(y_test, y_pred_test)
axs[1, 1].imshow(cm_test, interpolation='nearest', cmap=plt.cm.Blues)
axs[1, 1].set_title('Confusion Matrix - Teste - ' + nm_modelo)
axs[1, 1].set_xticks([0, 1])
axs[1, 1].set_yticks([0, 1])
axs[1, 1].set_xticklabels(['0', '1'])
axs[1, 1].set_yticklabels(['0', '1'])
thresh = cm_test.max() / 2.
for i, j in itertools.product(range(cm_test.shape[0]), range(cm_test.shape[1])):
axs[1, 1].text(j, i, format(cm_test[i, j], 'd'),
horizontalalignment="center",
color="white" if cm_test[i, j] > thresh else "black")
# ROC Curve - Treino e Teste
y_score_train = modelo.predict_proba(X_train)[:, 1]
fpr_train, tpr_train, _ = roc_curve(y_train, y_score_train)
axs[2, 0].plot(fpr_train, tpr_train, color=cor, label='Treino')
y_score_test = modelo.predict_proba(X_test)[:, 1]
fpr_test, tpr_test, _ = roc_curve(y_test, y_score_test)
axs[2, 0].plot(fpr_test, tpr_test, color='darkorange', label='Teste')
axs[2, 0].plot([0, 1], [0, 1], color='navy', linestyle='--')
axs[2, 0].set_title('ROC Curve - Treino e Teste - ' + nm_modelo)
axs[2, 0].set_xlabel('False Positive Rate')
axs[2, 0].set_ylabel('True Positive Rate')
axs[2, 0].legend(loc="lower right")
# Precision-Recall Curve - Treino e Teste
precision_train, recall_train, _ = precision_recall_curve(y_train, y_score_train)
axs[2, 1].plot(recall_train, precision_train, color=cor, label='Treino')
precision_test, recall_test, _ = precision_recall_curve(y_test, y_score_test)
axs[2, 1].plot(recall_test, precision_test, color='darkorange', label='Teste')
axs[2, 1].set_title('Precision-Recall Curve - Treino e Teste - ' + nm_modelo)
axs[2, 1].set_xlabel('Recall')
axs[2, 1].set_ylabel('Precision')
axs[2, 1].legend(loc="upper right")
# Gini - Treino e Teste
auc_train = roc_auc_score(y_train, y_score_train)
gini_train = 2 * auc_train - 1
auc_test = roc_auc_score(y_test, y_score_test)
gini_test = 2 * auc_test - 1
axs[3, 0].bar(['Treino', 'Teste'], [gini_train, gini_test], color=[cor, 'darkorange'])
axs[3, 0].set_title('Gini - ' + nm_modelo)
axs[3, 0].set_ylim(0, 1)
axs[3, 0].text('Treino', gini_train + 0.01, f'{gini_train:.2f}', ha='center', va='bottom')
axs[3, 0].text('Teste', gini_test + 0.01, f'{gini_test:.2f}', ha='center', va='bottom')
# KS - Treino e Teste
ks_train = calcular_ks_statistic(y_train, y_score_train)
ks_test = calcular_ks_statistic(y_test, y_score_test)
axs[3, 1].bar(['Treino', 'Teste'], [ks_train, ks_test], color=[cor, 'darkorange'])
axs[3, 1].set_title('KS - ' + nm_modelo)
axs[3, 1].set_ylim(0, 1)
axs[3, 1].text('Treino', ks_train + 0.01, f'{ks_train:.2f}', ha='center', va='bottom')
axs[3, 1].text('Teste', ks_test + 0.01, f'{ks_test:.2f}', ha='center', va='bottom')
# Decile Analysis - Teste
scores = modelo.predict_proba(X_test)[:, 1]
noise = np.random.uniform(0, 0.0001, size=scores.shape) # Adiciona um pequeno ruído
scores += noise
deciles = pd.qcut(scores, q=10, duplicates='drop')
decile_analysis = y_test.groupby(deciles, observed=False).mean()
axs[4, 1].bar(range(1, len(decile_analysis) + 1), decile_analysis, color='darkorange')
axs[4, 1].set_title('Ordenação do Score - Teste - ' + nm_modelo)
axs[4, 1].set_xlabel('Faixas de Score')
axs[4, 1].set_ylabel('Taxa de Evento')
# Decile Analysis - Treino
scores_train = modelo.predict_proba(X_train)[:, 1]
noise = np.random.uniform(0, 0.0001, size=scores_train.shape) # Adiciona um pequeno ruído
scores_train += noise
deciles_train = pd.qcut(scores_train, q=10, duplicates='drop')
decile_analysis_train = y_train.groupby(deciles_train, observed=False).mean()
axs[4, 0].bar(range(1, len(decile_analysis_train) + 1), decile_analysis_train, color=cor)
axs[4, 0].set_title('Ordenação do Score - Treino - ' + nm_modelo)
axs[4, 0].set_xlabel('Faixas de Score')
axs[4, 0].set_ylabel('Taxa de Evento')
# Mostrar os gráficos
plt.show()
caminho = 'D:/_jupyter/pod/ds/mod06-ciencia-de-dados/data/'
abt_titanic_csv = 'abt_titanic.csv'
import pandas as pd
abt_00 = pd.read_csv(caminho+abt_titanic_csv,index_col=0)
abt_00.head()
| Pclass | Age | SibSp | Parch | Ticket | Fare | Embarked | Titulo | Sex_male | Survived | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1.0 | 0.271174 | 0.125 | 0.0 | 523 | 0.014151 | 3 | 3 | 1.0 | 0 |
| 1 | 0.0 | 0.472229 | 0.125 | 0.0 | 596 | 0.139136 | 0 | 4 | 0.0 | 1 |
| 2 | 1.0 | 0.321438 | 0.000 | 0.0 | 669 | 0.015469 | 3 | 2 | 0.0 | 1 |
| 3 | 0.0 | 0.434531 | 0.125 | 0.0 | 49 | 0.103644 | 3 | 4 | 0.0 | 1 |
| 4 | 1.0 | 0.434531 | 0.000 | 0.0 | 472 | 0.015713 | 3 | 3 | 1.0 | 0 |
# Separando as variáveis de entrada (features) e de saída (target)
X_titanic = abt_00.drop(columns=["Survived"])
y_titanic = abt_00["Survived"]
from sklearn.model_selection import train_test_split
# Dividindo os dados em conjunto de treinamento e teste (70% treino, 30% teste)
X_train, X_test, y_train, y_test = train_test_split(X_titanic,
y_titanic,
test_size=0.3,
random_state=42)
X_train.shape,X_test.shape
((623, 9), (268, 9))
Como funciona:
Raiz: A árvore começa com a variável (feature) mais importante, que é aquela que melhor divide os dados. Essa variável é escolhida usando
critérios como o Gini Impurity ou a Entropia (para problemas de classificação) e o Erro Quadrático Médio (para regressão).
Divisões: O algoritmo continua dividindo os dados em subconjuntos, criando novos nós, até que certas condições sejam atendidas, como:
Folhas: Os nós finais da árvore são chamados de folhas, e eles representam as previsões do modelo.
Vantagens:
Desvantagens:
Hiperparâmetros da Árvore:
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import GridSearchCV
import numpy as np
%%time
# Definindo o modelo
model = DecisionTreeClassifier(random_state=42)
# Definindo os parâmetros para o grid search
param_grid = {
'criterion':['gini','entropy'],
'splitter':['best','random'],
'max_depth': [2,3,4], # Profundidade máxima da árvore
'min_samples_split': [0.008, 0.01,0.02,0.04], # Número mínimo de amostras necessárias para dividir um nó interno.
'min_samples_leaf': [0.008,0.02,0.04], # Número mínimo de amostras necessárias para estar em um nó folha.
}
# Calculando a quantidade total de modelos que serão treinados
# 5 é o número de folds na validação cruzada (cv)
num_models = len(param_grid['splitter']) * len(param_grid['criterion']) * len(param_grid['max_depth']) * len(param_grid['min_samples_split']) * len(param_grid['min_samples_leaf']) * 5
print(f"Total de Modelos a serem Treinados: {num_models}")
# Definindo o objeto GridSearchCV
grid = GridSearchCV(model,
param_grid,
cv=5,
scoring='roc_auc', # 'accuracy' 'precision' 'recall' 'f1'
n_jobs=-1)
# Treinando o modelo com o grid search
grid.fit(X_train, y_train)
# Exibindo os melhores parâmetros encontrados pelo grid search
print("Melhores Parâmetros: ", grid.best_params_)
# Exibindo a melhor pontuação (score) atingida pelo modelo com os melhores parâmetros
print("Melhor AUC: ", grid.best_score_)
# Utilizando o melhor modelo para fazer previsões
predictions = grid.best_estimator_.predict(X_test)
best_model_dt = grid.best_estimator_
Total de Modelos a serem Treinados: 720
Melhores Parâmetros: {'criterion': 'entropy', 'max_depth': 4, 'min_samples_leaf': 0.008, 'min_samples_split': 0.008, 'splitter': 'random'}
Melhor AUC: 0.8515684369690272
CPU times: total: 438 ms
Wall time: 5 s
avaliar_modelo(X_train, y_train, X_test, y_test, best_model_dt,nm_modelo='Árvore de Decisão')
Na regressão logística, a transformação logit da probabilidade de um evento é modelada como uma combinação linear das variáveis independentes, ou seja.
$ \ln\left(\frac{p}{1-p}\right) = \beta_0 + \beta_1x_1 + \beta_2x_2 + \ldots + \beta_kx_k $
onde $ p $ é a probabilidade do evento de interesse, $ \beta_0, \beta_1, \ldots, \beta_k $ são os coeficientes a serem estimados, e $ x_1, x_2, \ldots, x_k $ são as variáveis independentes.
A probabilidade $ p $ é então obtida por meio da função logística inversa
resultando em valores entre 0 e 1, que podem ser convertidos em classificações binárias, com base em um limiar, comumente 0,5.
Objetivo: Entender o conceito, a matemática e a aplicação da Regressão Logística em problemas de classificação binária.
Conteúdo:
Introdução à Regressão Logística:
Modelo Matemático:
onde $ P(Y=1) $ é a probabilidade do evento ocorrer, $ \beta_0 $ é o intercepto, $ \beta_1 $ é o coeficiente da variável $ X $, e $ e $ é a base do logaritmo natural.
Equação Logit:
Onde:
liblinear
newton-cg
lbfgs
sag
saga
Escolha do Solver:
Ao ajustar o modelo, é útil experimentar diferentes solvers para ver qual oferece o melhor desempenho para o seu conjunto de dados específico.
max_iter (Máximo de Iterações)
Este parâmetro determina o número máximo de iterações que o solver de otimização deve realizar antes de terminar. Isso é importante para
garantir que o solver não continue indefinidamente se não conseguir encontrar uma solução.
multi_class (Multi Classe)
Determina a estratégia para lidar com problemas de classificação multiclasse, pode ser ‘ovr’ (one-vs-rest) que treina um modelo
por classe ou ‘multinomial’ que treina um único modelo.
Estes são alguns dos principais parâmetros matemáticos e suas relações na regressão logística. Cada um desses parâmetros permite ao usuário
ajustar o modelo de acordo com as necessidades específicas de seu problema e conjunto de dados.
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV
import numpy as np
%%time
# Definindo o modelo
model = LogisticRegression(max_iter=100)
model_sgs = LogisticRegression(max_iter=100)
# penalty='l2', # Tipo de regularização: 'l1', 'l2', 'elasticnet', 'none'
# dual=False, # Formulação primal e dual do problema de otimização da regressão logística, sendo recomendado manter como False quando temos mais amostras do que Variáveis
# tol=0.0001, # Tolerância para critério de parada.
# C=1.0, # Inverso da força de regularização; deve ser um valor flutuante positivo. Como valores menores, especifica uma regularização mais forte.
# fit_intercept=True, # Especifica se uma constante (ou seja, viés ou interceptação) deve ser adicionada à função de decisão.
# intercept_scaling=1, # Útil apenas quando o solver 'liblinear' é usado e self.fit_intercept é definido como True.
# class_weight=None, # Pesos associados às classes. Se não for fornecido, todas as classes são supostas ter peso um.
# random_state=None, # Semente usada pelo gerador de números aleatórios.
# solver='lbfgs', # Algoritmo a ser usado no problema de otimização: {'newton-cg', 'lbfgs', 'liblinear', 'sag', 'saga'}, padrão='lbfgs'
# max_iter=100, # Número máximo de iterações para os solvers convergirem.
# multi_class='auto', # Se a opção escolhida for 'ovr', então um problema binário é ajustado para cada rótulo. Para 'multinomial', a perda minimizada é a perda multinomial ajustando todo o conjunto de dados de uma vez.
# verbose=0, # Para o solver 'liblinear' e 'lbfgs', defina o valor para qualquer inteiro positivo para classificar a verbosidade.
# warm_start=False, # Quando definido como True, reutiliza a solução da chamada anterior para ajustar como inicialização, caso contrário, apenas apaga a solução anterior.
# l1_ratio=None # O valor de Elastic-Net mixing parameter, com 0 <= l1_ratio <= 1. Somente usado se penalty='elasticnet'.
# Definindo os parâmetros para o grid search
param_grid = {
'penalty':['l1','l2'],
'tol':[0.00001,0.0001,0.001],
'C': [1.0, 2.0],
'solver':['liblinear', 'saga'],
'class_weight': [None, 'balanced', {0: 1, 1: 2}, {0: 2, 1: 1}]
}
# Calculando a quantidade total de modelos que serão treinados
num_models = len(param_grid['penalty']) * len(param_grid['tol']) * len(param_grid['C']) * len(param_grid['solver']) * 5 # 5 é o número de folds na validação cruzada (cv)
print(f"Total de Modelos a serem Treinados: {num_models}")
# Definindo o objeto GridSearchCV
grid = GridSearchCV(model,
param_grid,
cv=5,
scoring='roc_auc', # 'accuracy' 'precision' 'recall' 'f1'
n_jobs=-1)
# Treinando o modelo com o grid search
grid.fit(X_train, y_train)
# treinando modelo sem grid search para comparra
model_sgs.fit(X_train, y_train)
# Exibindo os melhores parâmetros encontrados pelo grid search
print("Melhores Parâmetros: ", grid.best_params_)
# Exibindo a melhor pontuação (score) atingida pelo modelo com os melhores parâmetros
print("Melhor AUC: ", grid.best_score_)
# Utilizando o melhor modelo para fazer previsões
predictions = grid.best_estimator_.predict(X_test)
best_model_rl = grid.best_estimator_
Total de Modelos a serem Treinados: 120
Melhores Parâmetros: {'C': 2.0, 'class_weight': {0: 1, 1: 2}, 'penalty': 'l1', 'solver': 'liblinear', 'tol': 0.001}
Melhor AUC: 0.8376319484915605
CPU times: total: 422 ms
Wall time: 2.17 s
avaliar_modelo(X_train, y_train, X_test, y_test, model_sgs,nm_modelo='Reg Logística')
avaliar_modelo(X_train, y_train, X_test, y_test, best_model_rl,nm_modelo='Reg Logística')
# coef_ retorna uma array 2D, então usamos [0] para obter a lista 1D de coeficientes.
coeficientes = best_model_rl.coef_[0]
# Criar um DataFrame com os nomes das variáveis e seus coeficientes correspondentes.
df_reglog = pd.DataFrame({'Variavel': list(X_train.columns),
'Coeficiente': coeficientes})
df_reglog['Importancia'] = df_reglog['Coeficiente'].abs().round(3)
df_reglog = df_reglog.sort_values(by='Importancia', ascending=False)
df_reglog
| Variavel | Coeficiente | Importancia | |
|---|---|---|---|
| 8 | Sex_male | -2.576940 | 2.577 |
| 2 | SibSp | -2.288095 | 2.288 |
| 1 | Age | -1.831583 | 1.832 |
| 0 | Pclass | -1.576960 | 1.577 |
| 5 | Fare | 1.048738 | 1.049 |
| 3 | Parch | -0.423976 | 0.424 |
| 7 | Titulo | -0.266219 | 0.266 |
| 6 | Embarked | -0.198404 | 0.198 |
| 4 | Ticket | -0.000179 | 0.000 |
Bagging e Boosting são técnicas de ensemble em aprendizado de máquina que buscam melhorar a acurácia e robustez dos modelos.
Bagging, que é uma abreviação de "Bootstrap Agregation", envolve construir múltiplos modelos (tipicamente do mesmo tipo) a partir de diferentes subconjuntos de
dados de treinamento, escolhidos aleatóriamente com reposição, e então agregar as previsões, geralmente através de votação majoritária para classificação ou média para regressão.
Já o Boosting foca em combinar múltiplos modelos fracos sequencialmente, onde cada modelo tenta corrigir os erros do seu antecessor.
Enquanto o bagging busca reduzir a variância do modelo, o boosting foca em reduzir o viés e é geralmente mais suscetível a "Overffiting" em comparação ao bagging.
O Random Forest é um método de ensemble learning que combina múltiplos modelos de árvore de decisão para criar um modelo mais robusto e preciso.
É particularmente eficaz para tarefas de classificação e regressão.
Como Funciona?
Bootstrap Aggregating (Bagging):
Árvores de Decisão:
Random Subspace Method:
Agregação:
Equações:
onde $ Y_{\text{tree}_i} $ é a previsão da i-ésima árvore.
Vantagens do Random Forest:
Robustez e Precisão:
Manipulação de Dados Ausentes:
Importância das Variáveis:
Aplicações:
O Random Forest é aplicável em várias áreas, como finanças para detecção de fraude, medicina para diagnóstico de doenças, e ciência de dados para classificação e regressão.
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV
import numpy as np
%%time
# Definindo o modelo
model = RandomForestClassifier()
# n_estimators=100, # Número de árvores na floresta.
# criterion='gini', # Função para medir a qualidade de uma divisão ("gini" ou "entropy").
# max_depth=None, # Profundidade máxima das árvores. None significa que os nós são expandidos até ficarem puros.
# min_samples_split=2, # Número mínimo de amostras necessárias para dividir um nó interno.
# min_samples_leaf=1, # Número mínimo de amostras necessárias para estar em um nó folha.
# min_weight_fraction_leaf=0.0, # Fração mínima ponderada da soma total de pesos necessária para estar em um nó folha.
# max_features='auto', # Número de características a considerar ao procurar a melhor divisão.
# max_leaf_nodes=None, # Número máximo de nós folha.
# min_impurity_decrease=0.0, # Um nó será dividido se a divisão induzir a uma diminuição da impureza maior ou igual a este valor.
# bootstrap=True, # Se as amostras de bootstrap são usadas ao construir árvores.
# oob_score=False, # Se usar amostras out-of-bag para estimar a precisão generalizada.
# n_jobs=None, # Número de jobs a serem executados em paralelo para ajuste e previsão. -1 significa usar todos os processadores.
# random_state=None, # Controla a aleatoriedade do bootstrap e da seleção de features.
# verbose=0, # Controla a verbosidade do processo de treinamento.
# warm_start=False, # Reutiliza a solução da chamada anterior para ajustar e adicionar mais estimadores ao ensemble.
# class_weight=None # Pesos associados às classes. Pode ser "balanced", "balanced_subsample" ou um dicionário com os pesos.
# Definindo os parâmetros para o grid search
param_grid = {
'n_estimators': [10, 50],
'max_depth': [2, 3, 5],
'min_samples_split': [0.001, 0.01],
'min_samples_leaf': [2, 0.01],
'bootstrap': [True, False],
# 'max_features': ['auto', 'sqrt', 'log2']
}
# Definindo o objeto GridSearchCV
grid = GridSearchCV(model,
param_grid,
cv=5,
verbose=2,
scoring='roc_auc', # 'accuracy' 'precision' 'recall' 'f1'
n_jobs=-1)
# Treinando o modelo com o grid search
grid.fit(X_train, y_train)
# Exibindo os melhores parâmetros encontrados pelo grid search
print("Melhores Parâmetros: ", grid.best_params_)
# Exibindo a melhor pontuação (score) atingida pelo modelo com os melhores parâmetros
print("Melhor AUC: ", grid.best_score_)
# Utilizando o melhor modelo para fazer previsões
predictions = grid.best_estimator_.predict(X_test)
best_model_rf = grid.best_estimator_
Fitting 5 folds for each of 48 candidates, totalling 240 fits
Melhores Parâmetros: {'bootstrap': True, 'max_depth': 5, 'min_samples_leaf': 0.01, 'min_samples_split': 0.01, 'n_estimators': 50}
Melhor AUC: 0.8649436761554586
CPU times: total: 406 ms
Wall time: 3.88 s
avaliar_modelo(X_train, y_train, X_test, y_test, best_model_rf,nm_modelo='Random Forest')
1. Modelo Aditivo: O modelo aditivo gerado pelo Gradient Boosting é definido como:
onde:
2. Função Objetivo e Otimização: O objetivo do Gradient Boosting é encontrar uma função $ F(x) $ que minimize a seguinte função objetivo:
onde:
3. Atualização Sequencial:
O Gradient Boosting constrói as árvores de forma sequencial. A cada passo, uma nova árvore é adicionada ao modelo para minimizar a função de perda, dado
o conjunto atual de árvores. Seja $ F_m(x) $ o modelo no passo $ m $, a árvore adicional é encontrada da seguinte maneira:
e o modelo é atualizado como:
onde $ \beta_m $ é a taxa de aprendizado.
4. Gradiente Negativo:
Para encontrar a árvore que minimiza a função de perda, o Gradient Boosting utiliza o conceito de gradiente negativo. Em cada passo, é calculado o gradiente negativo da função
de perda em relação às previsões do modelo atual, e uma árvore é ajustada para prever esses resíduos. Matematicamente, o gradiente negativo para a i-ésima observação é:
5. Regularização:
O Gradient Boosting inclui termos de regularização para evitar o overfitting, que podem incluir a profundidade máxima das árvores, o número mínimo de observações em
um nó folha, e penalizações para o número total de folhas de uma árvore.
Conclusão:
O Gradient Boosting é uma técnica poderosa e flexível que pode oferecer um desempenho preditivo de alta qualidade em uma variedade de problemas de aprendizado de máquina,
sendo especialmente útil em contextos onde o desempenho preditivo é crítico.
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.model_selection import GridSearchCV
import numpy as np
%%time
# Definindo o modelo
model = GradientBoostingClassifier(random_state=42)
# Definindo os parâmetros para o grid search
param_grid = {
'learning_rate': [0.01, 0.1],
'n_estimators': [100, 200],
'max_depth': [3, 5, 7],
'min_samples_split': [2, 4],
'min_samples_leaf': [1, 2],
'subsample': [0.8, 0.9],
'max_features': ['sqrt', 'log2', None]
}
# Definindo o objeto GridSearchCV
grid = GridSearchCV(model,
param_grid,
cv=5,
verbose=2,
scoring='roc_auc', # 'accuracy' 'precision' 'recall' 'f1'
n_jobs=-1)
# Treinando o modelo com o grid search
grid.fit(X_train, y_train)
# Exibindo os melhores parâmetros encontrados pelo grid search
print("Melhores Parâmetros: ", grid.best_params_)
# Exibindo a melhor pontuação (score) atingida pelo modelo com os melhores parâmetros
print("Melhor AUC: ", grid.best_score_)
# Utilizando o melhor modelo para fazer previsões
predictions = grid.best_estimator_.predict(X_test)
best_model_gbm = grid.best_estimator_
Fitting 5 folds for each of 288 candidates, totalling 1440 fits
Melhores Parâmetros: {'learning_rate': 0.01, 'max_depth': 7, 'max_features': 'sqrt', 'min_samples_leaf': 1, 'min_samples_split': 4, 'n_estimators': 100, 'subsample': 0.8}
Melhor AUC: 0.8714340466966377
CPU times: total: 3 s
Wall time: 2min 57s
avaliar_modelo(X_train, y_train, X_test, y_test, best_model_gbm,nm_modelo='Gradient Boosting')
https://lightgbm.readthedocs.io/en/stable/
Vamos entender um pouco mais sobre como ele funciona, suas vantagens, e seus parâmetros.
Trata-se de uma implementação eficiente e escalável do Gradient Boosting, que permite construir modelos de alta precisão, sendo capaz de lidar com conjuntos de dados de grande escala.
Seu conjunto extenso de parâmetros permite um ajuste fino do modelo de acordo com as necessidades específicas de diferentes problemas de aprendizado de máquina.
Como Funciona o LightGBM:
Vantagens do LightGBM:
O LightGBM, sendo um método de boosting baseado em árvores, envolve muitos conceitos e cálculos.
Abaixo, vou resumir algumas das principais equações e conceitos envolvidos no treinamento de um modelo LightGBM.
Onde:
Onde:
Para classificação binária, uma escolha comum é a perda logística:
Onde:
Essas equações e conceitos são fundamentais para entender o funcionamento interno do LightGBM. Cada passo do algoritmo envolve a otimização desses componentes para
construir um modelo que minimiza a função de perda enquanto mantém a complexidade do modelo sob controle.
Para problemas de classificação, o LightGBM, assim como outros métodos de boosting baseados em árvores, utiliza o conceito de votação de árvores para determinar a classe
final predita. Vou explicar como isso é feito, focando em classificação binária e multiclasse.
Classificação Binária:
Para classificação binária, as árvores no modelo de boosting são usadas para modelar o log-odds (logit) da probabilidade da classe positiva. A combinação das árvores
dá o valor final do logit, que é então transformado em uma probabilidade via função logística, e a classificação final é decidida com base nessa probabilidade.
A fórmula para o logit (log-odds) é:
Onde $ f_k(x_i) $ é a previsão da k-ésima árvore para a i-ésima amostra.
Para converter o logit para uma probabilidade, usamos a função logística (sigmoid):
Finalmente, a classe predita $ \hat{y_i} $ é determinada com base na probabilidade:
Classificação Multiclasse:
Para problemas de classificação com mais de duas classes, o LightGBM utiliza o método de One-vs-All (OvA) para construir um modelo para cada classe contra
todas as outras. Para cada classe $ j $, é construído um modelo para estimar a probabilidade $ P(y = j | x) $.
A probabilidade para a classe $ j $ é calculada usando a função softmax:
Onde:
A classe final predita $ \hat{y_i} $ é então a classe com a maior probabilidade:
As árvores no modelo LightGBM, em conjunto, votam para calcular a probabilidade de uma amostra pertencer a uma determinada classe, e a classe final
é escolhida com base nessas probabilidades, seja através de um limiar, no caso de classificação binária, ou escolhendo a classe com a maior probabilidade, no caso de classificação multiclasse.
O uso do Hessiano, ou da segunda derivada da função de perda, traz várias vantagens no contexto dos métodos de boosting, como o LightGBM, especialmente
em relação à eficiência e precisão da otimização.
1. Informação da Curvatura:
2. Ajuste Adaptativo da Taxa de Aprendizado:
3. Otimização de Segunda Ordem:
4. Corte de Folhas Baseado em Ganho:
Exemplo Simples: Considere uma função de perda quadrática $ L(y, \hat{y}) = \frac{1}{2}(y - \hat{y})^2 $. O gradiente e o Hessiano são, respectivamente:
Neste caso, o Hessiano é constante, mas em funções de perda mais complexas ou não-convexas, ele varia e fornece informações valiosas sobre a forma da
função de perda, ajudando na otimização do modelo.
O Hessiano, ao prover informações adicionais sobre a curvatura da função de perda, permite uma otimização mais sofisticada e adaptativa, podendo resultar em modelos mais precisos
e eficientes em termos computacionais, especialmente em casos onde a função de perda é complexa e não-convexa.
Aqui estão alguns dos principais parâmetros do LightGBM e uma breve descrição de cada um:
import lightgbm as lgb
from sklearn.model_selection import GridSearchCV
import numpy as np
%%time
# Definindo o modelo
model = lgb.LGBMClassifier(verbose=-1)
# Definindo os parâmetros para o grid search
param_grid = {
'max_depth' : [2,3],
'num_leaves': [5, 31],
'reg_alpha': [0.1, 0.5],
'min_data_in_leaf': [2, 5],
'lambda_l1': [0, 1, 1.5],
'lambda_l2': [0, 1]
}
# Definindo o objeto GridSearchCV
grid = GridSearchCV(model,
param_grid,
cv=5,
verbose=2,
scoring='roc_auc', # 'accuracy' 'precision' 'recall' 'f1'
n_jobs=-1)
# Treinando o modelo com o grid search
grid.fit(X_train, y_train)
# Exibindo os melhores parâmetros encontrados pelo grid search
print("Melhores Parâmetros: ", grid.best_params_)
# Exibindo a melhor pontuação (score) atingida pelo modelo com os melhores parâmetros
print("Melhor AUC: ", grid.best_score_)
# Utilizando o melhor modelo para fazer previsões
predictions = grid.best_estimator_.predict(X_test)
best_model_lightgbm = grid.best_estimator_
Fitting 5 folds for each of 96 candidates, totalling 480 fits
Melhores Parâmetros: {'lambda_l1': 0, 'lambda_l2': 1, 'max_depth': 2, 'min_data_in_leaf': 5, 'num_leaves': 5, 'reg_alpha': 0.1}
Melhor AUC: 0.8651497450429522
CPU times: total: 297 ms
Wall time: 8.08 s
avaliar_modelo(X_train, y_train, X_test, y_test, best_model_lightgbm,nm_modelo='LightGBM')
O XGBoost (eXtreme Gradient Boosting) é uma implementação eficiente e escalável do algoritmo de Gradient Boosting, projetada para ser mais rápida e melhor performática.
Ele é amplamente utilizado em competições de ciência de dados devido à sua flexibilidade e alta capacidade preditiva.
1. Modelo Aditivo e Função Objetivo:
Assim como outros métodos de boosting, o XGBoost constrói um modelo aditivo de forma sequencial, com o objetivo de minimizar uma função objetivo que consiste
em uma função de perda e um termo de regularização:
2. Regularização:
O termo de regularização no XGBoost é um dos elementos que o diferenciam de outras implementações de boosting. Ele é formulado como:
3. Otimização e Método de Newton-Raphson:
4. Pruning:
5. Equações de Classificação e Regressão:
A função Softmax é uma função de ativação que transforma vetores de números reais em um vetor de valores de probabilidade. Ela é frequentemente usada em problemas
de classificação multiclasse para transformar os scores brutos (logits) de um modelo em probabilidades para cada classe.
Na saída de modelos de aprendizado de máquina para classificação multiclasse, como redes neurais ou modelos de regressão logística multiclasse, a função Softmax é frequentemente
usada para converter os scores brutos em probabilidades. A classe prevista para uma dada amostra é então simplesmente a classe com a maior probabilidade segundo a função Softmax.
Formulação da Função Softmax:
Dado um vetor $ z = [z_1, z_2, ..., z_K] $ de scores brutos (logits) para cada uma das $ K $ classes, a função Softmax transforma esses scores em probabilidades através da seguinte fórmula:
Onde:
Taxa de aprendizado, determina o passo no ajuste dos pesos.
Número de árvores a serem construídas.
Profundidade máxima de uma árvore. Valores maiores podem levar a overfitting.
Controle de overfitting. Valores maiores podem levar a underfitting.
Fração de colunas (features) a serem amostradas para construir cada árvore.
Fração de observações amostradas para construir cada árvore.
Parâmetro de regularização L1 nos pesos das folhas.
Parâmetro de regularização L2 nos pesos das folhas.
Uma semente para reprodutibilidade.
Métrica de avaliação a ser usada na validação.
Desativa o uso do label encoder para evitar warnings com versões mais recentes do XGBoost.
A log loss, ou logaritmic loss, também conhecida como cross-entropy loss, é uma métrica de erro frequentemente usada em problemas de classificação binária e multiclasse para avaliar a
precisão das previsões de probabilidade de um modelo.
1. Log Loss para Classificação Binária:
Para a classificação binária, onde temos duas classes, 0 e 1, a fórmula da log loss para uma única observação é:
Onde:
A log loss para um conjunto de $ N $ observações é a média das log losses para cada observação:
2. Log Loss para Classificação Multiclasse:
Para problemas de classificação multiclasse, a log loss se estende para lidar com múltiplas classes. Se temos $ C $ classes, a log loss para uma única observação é:
Onde:
A log loss para um conjunto de $ N $ observações é a média das log losses para cada observação:
Propriedades da Log Loss:
import xgboost as xgb
from sklearn.model_selection import GridSearchCV
import numpy as np
%%time
# Definir o modelo
model = xgb.XGBClassifier(use_label_encoder=False, eval_metric='mlogloss')
# Definindo os parâmetros para o grid search
param_grid = {
'learning_rate': [0.01, 0.1],
'max_depth': [3, 5],
'min_child_weight': [1, 3],
'subsample': [0.5, 0.7, 1.0],
'colsample_bytree': [0.5, 0.7],
'n_estimators': [10, 100]
}
# Definindo o objeto GridSearchCV
grid = GridSearchCV(model,
param_grid,
cv=5,
verbose=2,
scoring='roc_auc', # 'accuracy' 'precision' 'recall' 'f1'
n_jobs=-1)
# Treinando o modelo com o grid search
grid.fit(X_train, y_train)
# Exibindo os melhores parâmetros encontrados pelo grid search
print("Melhores Parâmetros: ", grid.best_params_)
# Exibindo a melhor pontuação (score) atingida pelo modelo com os melhores parâmetros
print("Melhor AUC: ", grid.best_score_)
# Utilizando o melhor modelo para fazer previsões
predictions = grid.best_estimator_.predict(X_test)
best_model_xgbm = grid.best_estimator_
Fitting 5 folds for each of 96 candidates, totalling 480 fits
Melhores Parâmetros: {'colsample_bytree': 0.7, 'learning_rate': 0.1, 'max_depth': 5, 'min_child_weight': 3, 'n_estimators': 100, 'subsample': 0.7}
Melhor AUC: 0.8769776773342389
CPU times: total: 703 ms
Wall time: 4.28 s
avaliar_modelo(X_train, y_train, X_test, y_test, best_model_xgbm,nm_modelo='XGBoost')
O CatBoost é uma biblioteca de apredizado de máquina desenvolvida pela Yandex, projetada especialmente para lidar eficientemente com variáveis categóricas, eliminando
a necessidade de pré-processamento extensivo, como one-hot encoding.
O nome "CatBoost" deriva de "Category"e "Boosting". Ele é baseado na técnica de gradient boosting e é particularmente eficaz e eficiente, proporcionando
resultados de alta qualidade com configurações de parâmetros padrão.
O CatBoost também implementa várias entratégias de regularização para prevenir overfitting, oferece a capacidade de treinar modelos de forma incremental
e é adaptável para resolver tarefas de classificação, regressão e ranking,
Devido à sua robustez e facilidade de uso, o CatBoost tem ganhado popularidade na comunidade de ciência de dados para uma variedade de aplicações práticas.
1. Modelo Aditivo e Função Objetivo:
Semelhante a outros métodos de boosting, o CatBoost constrói um modelo aditivo:
onde $f_k(x)$ são funções base (neste caso, árvores de decisão), e $T$ é o número total de árvores. O CatBoost tem como objetivo minimizar a seguinte função objetivo:
onde $\text{Loss}(\mathbf{y}, \hat{\mathbf{y}})$ é a função de perda, dependente do problema, e $\text{Regularization}$ é um termo de regularização.
2. Tratamento de Características Categóricas:
A principal característica do CatBoost é sua capacidade de lidar com variáveis categóricas. Ele utiliza um método chamado "ordered boosting", que elimina o risco de
vazamento de dados durante o cálculo de estatísticas de características categóricas.
3. Regularização:
O CatBoost utiliza a regularização para evitar o overfitting, semelhante ao XGBoost e ao LightGBM. No entanto, a formulação exata do termo de regularização é proprietária do algoritmo CatBoost.
4. Ordered Boosting:
O CatBoost introduz um esquema de boosting chamado "ordered boosting", que busca evitar o overfitting ao lidar com a escolha de splits nas variáveis categóricas.
Isso é feito utilizando diferentes esquemas de permutação para calcular as estatísticas das características categóricas durante o treinamento, o que ajuda a evitar
o vazamento de informações e melhora a robustez do modelo.
5. Função de Perda e Problemas de Classificação e Regressão:
O CatBoost pode ser utilizado para problemas de classificação binária, multiclasse e regressão. A função de perda é escolhida de acordo com o problema:
6. Eficiência Computacional:
O CatBoost é otimizado para ser eficiente em termos de memória e tempo de execução e é paralelizável, o que permite treinar modelos em conjuntos de dados grandes de forma eficiente.
Conclusão:
O CatBoost é um algoritmo de boosting robusto e eficiente que é especialmente útil quando se lida com variáveis categóricas, devido ao seu tratamento inovador dessas variáveis.
Ele fornece alta performance e precisão em uma variedade de problemas, com a capacidade de lidar eficientemente com conjuntos de dados grandes e complexos.
from catboost import CatBoostClassifier
from sklearn.model_selection import GridSearchCV
import numpy as np
%%time
# Definir o modelo
model = xgb.XGBClassifier(use_label_encoder=False, eval_metric='mlogloss')
# Definindo os parâmetros para o grid search
param_grid = {
'learning_rate': [0.01, 0.1],
'depth': [6, 8],
'l2_leaf_reg': [1, 3],
'iterations': [100, 200]
}
# Definindo o objeto GridSearchCV
grid = GridSearchCV(model,
param_grid,
cv=5,
verbose=2,
scoring='roc_auc', # 'accuracy' 'precision' 'recall' 'f1'
n_jobs=-1)
# Treinando o modelo com o grid search
grid.fit(X_train, y_train)
# Exibindo os melhores parâmetros encontrados pelo grid search
print("Melhores Parâmetros: ", grid.best_params_)
# Exibindo a melhor pontuação (score) atingida pelo modelo com os melhores parâmetros
print("Melhor AUC: ", grid.best_score_)
# Utilizando o melhor modelo para fazer previsões
predictions = grid.best_estimator_.predict(X_test)
best_model_catbst = grid.best_estimator_
Fitting 5 folds for each of 16 candidates, totalling 80 fits
Melhores Parâmetros: {'depth': 6, 'iterations': 100, 'l2_leaf_reg': 1, 'learning_rate': 0.1}
Melhor AUC: 0.8683085071854262
CPU times: total: 375 ms
Wall time: 2.16 s
avaliar_modelo(X_train, y_train, X_test, y_test, best_model_catbst,nm_modelo='CatBoost')
O algoritmo k-Nearest Neighbors (k-NN) é um método simples e intuitivo de aprendizado de máquina usado para classificação e regressão. Ele é um tipo de aprendizado
baseado em instância ou aprendizado preguiçoso, onde a função é aproximada localmente e todo o cálculo é adiado até a avaliação da função.
1. Princípio Básico:
O k-NN funciona calculando a distância entre uma amostra de teste e todas as amostras de treinamento. As $k$ amostras de treinamento mais próximas são
selecionadas, e a previsão é feita com base nessas amostras.
2. Classificação:
Para um problema de classificação, o k-NN atribui a uma amostra de teste a classe que é mais frequente entre seus $k$ vizinhos mais próximos.
Onde:
3. Regressão:
Para um problema de regressão, o k-NN atribui à amostra de teste a média (ou mediana) dos valores de saída de seus $k$ vizinhos mais próximos.
Onde:
4. Distância:
A medida de distância mais comumente usada no k-NN é a distância Euclidiana:
Onde:
5. Exemplo com Python:
O Scikit-Learn possui uma implementação do k-NN chamada 'KNeighborsClassifier' para classificação e 'KNeighborsRegressor' para regressão.
6. Pontos a Considerar:
Para o algoritmo k-NN, a forma como as previsões são feitas varia entre tarefas de regressão e classificação.
1. Regressão:
Na regressão, o k-NN calcula a média (ou em alguns casos, a mediana) dos valores das $ k $ observações mais próximas ao ponto de consulta.
A equação para a previsão de regressão é:
Onde:
2. Classificação:
Na classificação, o k-NN atribui a classe mais frequente entre as $ k $ observações mais próximas ao ponto de consulta.
A equação para a previsão de classificação não é uma equação numérica tradicional, mas pode ser representada como:
Onde:
Distância:
Ambos, regressão e classificação com k-NN, utilizam métricas de distância (como a distância Euclidiana) para encontrar os $ k $ vizinhos mais próximos:
Onde:
A distância de Manhattan entre dois pontos $x$ e $y$ em um espaço $n$-dimensional é calculada como a soma das diferenças absolutas de suas coordenadas. A equação para a distância de Manhattan é:
Onde:
A distância de Minkowski é uma métrica de distância em um espaço normado. É uma generalização das distâncias Euclidiana e Manhattan. A equação para a distância de Minkowski é:
Onde:
Observações:
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import GridSearchCV
import numpy as np
%%time
# Definir o modelo
model = KNeighborsClassifier()
# Definindo os parâmetros para o grid search
param_grid = {
'n_neighbors': [1, 3, 5, 7, 9, 11, 13, 15],
'weights': ['uniform', 'distance'],
'metric': ['euclidean', 'manhattan', 'minkowski']
}
# Calculando a quantidade total de modelos que serão treinados
# num_models = len(param_grid['penalty']) * len(param_grid['tol']) * len(param_grid['C']) * len(param_grid['solver']) * 5 # 5 é o número de folds na validação cruzada (cv)
# print(f"Total de Modelos a serem Treinados: {num_models}")
# Definindo o objeto GridSearchCV
grid = GridSearchCV(model,
param_grid,
cv=5,
verbose=2,
scoring='roc_auc', # 'accuracy' 'precision' 'recall' 'f1'
n_jobs=-1)
# Treinando o modelo com o grid search
grid.fit(X_train, y_train)
# Exibindo os melhores parâmetros encontrados pelo grid search
print("Melhores Parâmetros: ", grid.best_params_)
# Exibindo a melhor pontuação (score) atingida pelo modelo com os melhores parâmetros
print("Melhor AUC: ", grid.best_score_)
# Utilizando o melhor modelo para fazer previsões
predictions = grid.best_estimator_.predict(X_test)
best_model_knn = grid.best_estimator_
Fitting 5 folds for each of 48 candidates, totalling 240 fits
Melhores Parâmetros: {'metric': 'manhattan', 'n_neighbors': 15, 'weights': 'distance'}
Melhor AUC: 0.7722374098537753
CPU times: total: 281 ms
Wall time: 877 ms
avaliar_modelo(X_train, y_train, X_test, y_test, best_model_knn,nm_modelo='KNN')
As Redes Neurais Multilayer Perceptron (MLP) são uma classe de redes neurais artificiais estruturadas em múltiplas camadas, incluindo uma camada de entrada, uma ou
mais camadas ocultas e uma camada de saída.
Cada neurônio, ou unidade de processamento, em uma camada está conectado a todos os neurônios da camada seguinte por meio de pesos sinápticos.
O MLP utiliza uma função de ativação não-linear, como a função sigmoide ou ReLU, permitindo que o modelo capture relações complexas e não-lineares entre as entradas e saídas.
O treinamento do MLP é comumente realizado através do algoritmo de retropropagação (backpropagation), que ajusta os pesos sinápticos para minimizar a diferença entre
as previsões do modelo e os valores verdadeiros, utilizando técnicas de otimização como o Gradiente Descendente.
As redes MLP são aplicadas em uma ampla gama de tarefas de aprendizado de máquina, como classificação, regressão e reconhecimento de padrões, sendo fundamentais para
o desenvolvimento de modelos mais sofisticados de aprendizado profundo.
As Redes Neurais Multilayer Perceptron (MLP) envolvem várias equações para representar a propagação para a frente (feedforward), a função de ativação, a função de custo e a retropropagação (backpropagation).
Onde:
Onde:
Onde:
Essas são equações simplificadas para ilustrar os componentes principais de uma MLP. Em prática, uma MLP terá muitos neurônios em cada camada, e cada neurônio terá seu próprio
conjunto de pesos e vieses, que são ajustados durante o treinamento.
As funções de ativação são fundamentais em redes neurais, pois introduzem não-linearidades ao modelo, permitindo que a rede aprenda relações complexas entre as entradas e saídas.
Aqui estão as equações para cinco funções de ativação comumente usadas:
Cada uma dessas funções de ativação tem suas próprias características e é adequada para diferentes tipos de camadas e arquiteturas de rede.
Na Rede Neural Multilayer Perceptron (MLP), a equação de saída varia dependendo se o problema é de regressão ou classificação.
1. Para Regressão:
Onde:
2. Para Classificação Binária:
Onde:
3. Para Classificação Multiclasse:
Onde:
Nota:
from sklearn.neural_network import MLPClassifier
from sklearn.model_selection import GridSearchCV
import numpy as np
%%time
# Definir o modelo
model = MLPClassifier(max_iter=1000, random_state=42)
# Definindo os parâmetros para o grid search
param_grid = {
'hidden_layer_sizes': [(50,), (50, 50)],
'activation': ['tanh', 'relu'],
'solver': ['sgd', 'adam'],
'alpha': [0.0001, 0.05],
'learning_rate': ['constant', 'adaptive'],
}
# Definindo o objeto GridSearchCV
grid = GridSearchCV(model,
param_grid,
cv=5,
verbose=2,
scoring='roc_auc', # 'accuracy' 'precision' 'recall' 'f1'
n_jobs=-1)
# Treinando o modelo com o grid search
grid.fit(X_train, y_train)
# Exibindo os melhores parâmetros encontrados pelo grid search
print("Melhores Parâmetros: ", grid.best_params_)
# Exibindo a melhor pontuação (score) atingida pelo modelo com os melhores parâmetros
print("Melhor AUC: ", grid.best_score_)
# Utilizando o melhor modelo para fazer previsões
predictions = grid.best_estimator_.predict(X_test)
best_model_mlp = grid.best_estimator_
Fitting 5 folds for each of 32 candidates, totalling 160 fits
Melhores Parâmetros: {'activation': 'tanh', 'alpha': 0.05, 'hidden_layer_sizes': (50, 50), 'learning_rate': 'constant', 'solver': 'adam'}
Melhor AUC: 0.8487093765885086
CPU times: total: 2.97 s
Wall time: 17.1 s
avaliar_modelo(X_train, y_train, X_test, y_test, best_model_mlp,nm_modelo='MLP')
O Support Vector Machine (SVM) é um modelo poderoso e versátil de aprendizado de máquina, amplamente utilizado para tarefas de classificação e regressão.
O princípio fundamental do SVM é encontrar o hiperplano que separa as diferentes classes no espaço de características de maneira ótima, sendo este definido como o hiperplano
que maximiza a margem entre as classes mais próximas, chamadas de vetores de suporte.
Em casos não linearmente separáveis, o SVM utiliza funções de kernel, como o kernel polinomial ou o kernel RBF (Radial Basis Function), para mapear os dados para um espaço
de dimensão superior onde eles possam ser linearmente separados, uma técnica conhecida como truque do kernel.
O SVM é valorizado por sua robustez e eficácia em espaços de alta dimensão e situações onde a margem de separação entre as classes é pequena, sendo uma ferramenta essencial
para cientistas de dados em diversas aplicações práticas.
O Support Vector Machine (SVM) tem como objetivo encontrar um hiperplano que separe as classes ou que faça a regressão de forma ótima. Vamos detalhar as principais equações, começando com classificação e depois abordando regressão:
1. SVM para Classificação:
Onde $ w $ é o vetor normal ao hiperplano, $ x $ são os pontos no espaço de características, e $ b $ é o viés.
Onde a função $\text{sign}(\cdot)$ retorna +1 se o argumento é positivo (pertence à classe +1) e -1 se o argumento é negativo (pertence à classe -1).
Quando se lida com dados não linearmente separáveis, usa-se o truque do kernel para mapear os dados para um espaço de maior dimensão. A função de kernel mais usada é a RBF:
Onde $ \gamma > 0 $ é o parâmetro do kernel RBF.
2. SVM para Regressão (SVR - Support Vector Regression):
Onde o objetivo é fazer com que $ f(x) $ esteja o mais próximo possível dos valores de saída $ y_i $ para todos os pontos de dados, com uma tolerância de erro $ \epsilon $.
Onde:
Resumo:
Para converter as saídas de um modelo de classificação, como SVM, em probabilidades, uma abordagem comum é usar a função logística (ou sigmoide) aplicada à distância
da instância até o hiperplano de decisão.
A ideia é mapear a distância de um ponto até o hiperplano de uma maneira que valores grandes (ponto longe do hiperplano no lado positivo) se aproximem de 1, e valores
pequenos (ponto longe do hiperplano no lado negativo) se aproximem de 0.
A função sigmoide, que é usada para este propósito, tem a forma:
Onde:
SVM com Probabilidade no scikit-learn:
No scikit-learn, o SVM tem um parâmetro probability que, quando definido como True, faz com que o modelo ajuste uma regressão logística sobre as pontuações da função de decisão para obter probabilidades.
Isso é feito usando validação cruzada e, consequentemente, pode aumentar significativamente o tempo de treinamento do modelo.
Exemplo de Código:
python
from sklearn import svm
Criar um SVM com um kernel RBF
classifier = svm.SVC(kernel='rbf', probability=True)
Treinar o modelo com os dados de treinamento (X_train, y_train)
classifier.fit(X_train, y_train)
Obter as probabilidades para os dados de teste (ou novos dados)
probabilities = classifier.predict_proba(X_test)
Neste exemplo, 'probabilities' será um array onde cada linha corresponde a uma instância de teste e cada coluna contém a probabilidade da instância pertencer a uma classe.
Em otimização matemática, o problema primal refere-se ao problema de otimização original que se deseja resolver.
Muitas vezes, ao resolver problemas de otimização, particularmente em aprendizado de máquina e pesquisa operacional, é comum formular um problema dual associado ao problema primal.
O problema dual é derivado do problema primal e, em muitos casos, pode ser mais fácil de resolver, oferecendo ainda insights sobre o problema primal.
Formulação Primal:
Dado um problema de otimização genérico, o problema primal pode ser formulado da seguinte maneira:
Onde:
Exemplo: Problema Primal no SVM:
No contexto de Support Vector Machines (SVM), o problema primal é encontrar o hiperplano de separação que maximiza a margem entre duas classes, enquanto minimiza a soma
das distâncias dos pontos mal classificados ao hiperplano. O problema primal do SVM pode ser formulado como:
Onde:
Problema Dual:
O problema dual, derivado do primal, frequentemente envolve a maximização da função lagrangiana dual, e suas variáveis são os multiplicadores de Lagrange
associados às restrições do problema primal.
Resolver o problema dual pode oferecer insights e propriedades úteis relacionadas ao problema primal, e em muitos casos, a solução do problema dual fornece
uma maneira de encontrar a solução do problema primal.
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV
import numpy as np
%%time
# Definir o modelo
model = SVC(probability=True)
# Definindo os parâmetros para o grid search
param_grid = {
'C': [0.1, 1],
'kernel': ['linear'],
# 'degree': [2, 3], # Só é relevante se kernel='poly'
'gamma': [0.1, 1]
}
# Definindo o objeto GridSearchCV
grid = GridSearchCV(model,
param_grid,
cv=5,
verbose=2,
scoring='roc_auc', # 'accuracy' 'precision' 'recall' 'f1'
n_jobs=-1)
# Treinando o modelo com o grid search
grid.fit(X_train, y_train)
# Exibindo os melhores parâmetros encontrados pelo grid search
print("Melhores Parâmetros: ", grid.best_params_)
# Exibindo a melhor pontuação (score) atingida pelo modelo com os melhores parâmetros
print("Melhor AUC: ", grid.best_score_)
# Utilizando o melhor modelo para fazer previsões
predictions = grid.best_estimator_.predict(X_test)
best_model_svm = grid.best_estimator_
Fitting 5 folds for each of 4 candidates, totalling 20 fits
Melhores Parâmetros: {'C': 0.1, 'gamma': 0.1, 'kernel': 'linear'}
Melhor AUC: 0.835162980050508
CPU times: total: 57.1 s
Wall time: 5min 39s
avaliar_modelo(X_train, y_train, X_test, y_test, best_model_svm,nm_modelo='SVM')
O stacking de modelos é uma técnica de aprendizado de conjunto que busca combinar múltiplos modelos de aprendizado de máquina para melhorar o desempenho preditivo geral.
Nessa abordagem, diferentes modelos, chamados de modelos de base, são treinados usando o conjunto de dados de treinamento e, em seguida, um modelo meta-aprendiz
(ou meta-modelo) é treinado para fazer previsões finais baseadas nas previsões dos modelos de base.
Os modelos de base podem ser diferentes tipos de modelos ou o mesmo tipo de modelo com diferentes configurações de hiperparâmetros.
O meta-modelo aprende como otimizar a combinação das previsões dos modelos de base de forma a produzir uma previsão final mais precisa e robusta.
O stacking é particularmente útil quando os modelos de base têm diferentes forças e fraquezas em relação a diferentes partes do espaço de entrada, permitindo que
o modelo de conjunto tire proveito da diversidade dos modelos de base para alcançar um desempenho superior.
No contexto do stacking de modelos, tanto para classificação quanto para regressão, as equações envolvidas são principalmente relacionadas à forma como o meta-modelo
faz previsões baseadas nas previsões dos modelos de base.
1. Para Regressão:
Modelos de Base:
Suponha que temos $ M $ modelos de base e queremos fazer previsões para uma instância $ x $. Cada modelo de base $ m_i $ produzirá uma previsão $ \hat{y}_i $.
Meta-Modelo:
O meta-modelo é treinado para fazer previsões $ \hat{y} $ usando as previsões dos modelos de base como entradas.
2. Para Classificação:
Modelos de Base:
Para a classificação, cada modelo de base $ m_i $ produzirá uma probabilidade $ p_i $ da instância $ x $ pertencer à classe positiva.
Meta-Modelo:
O meta-modelo é então treinado para fazer previsões de classe (ou probabilidades de classe) usando as probabilidades dos modelos de base como entradas.
Onde $ \hat{p} $ é a probabilidade prevista da instância $ x $ pertencer à classe positiva, e a classe final prevista será determinada com base em um limiar, como 0.5 em problemas binários.
Nota:
A função $ f $ do meta-modelo pode ser qualquer modelo de aprendizado de máquina adequado, como uma regressão logística para problemas de classificação, ou uma regressão linear para
problemas de regressão, dependendo do problema específico em questão.
O treinamento do meta-modelo envolve o uso de um conjunto de validação ou de um procedimento de validação cruzada para evitar o ajuste excessivo ao conjunto de treinamento.
from sklearn.ensemble import StackingClassifier
from sklearn.linear_model import LogisticRegression
%%time
# Definir os modelos de base
base_learners = [
('dt', best_model_dt),
('rl', best_model_rl),
('rf', best_model_rf),
('gbm', best_model_gbm),
('lgbm', best_model_lightgbm),
('xgbm', best_model_xgbm),
('ctbst', best_model_catbst),
('knn', best_model_knn),
('mlp', best_model_mlp),
('svc', best_model_svm)
]
# Definir o meta-modelo
meta_learner = LogisticRegression(random_state=42)
# Construir o modelo de stacking
stacking_model = StackingClassifier(estimators=base_learners, final_estimator=meta_learner)
# Treinar o modelo de stacking
stacking_model.fit(X_train, y_train)
stacking_model
CPU times: total: 5min 11s Wall time: 5min 3s
StackingClassifier(estimators=[('dt',
DecisionTreeClassifier(criterion='entropy',
max_depth=4,
min_samples_leaf=0.008,
min_samples_split=0.008,
random_state=42,
splitter='random')),
('rl',
LogisticRegression(C=2.0,
class_weight={0: 1, 1: 2},
penalty='l1',
solver='liblinear',
tol=0.001)),
('rf',
RandomForestClassifier(max_depth=5,
min_samples_leaf=0.01,
min_samples_sp...
multi_strategy=None,
n_estimators=None, ...)),
('knn',
KNeighborsClassifier(metric='manhattan',
n_neighbors=15,
weights='distance')),
('mlp',
MLPClassifier(activation='tanh', alpha=0.05,
hidden_layer_sizes=(50, 50),
max_iter=1000, random_state=42)),
('svc',
SVC(C=0.1, gamma=0.1, kernel='linear',
probability=True))],
final_estimator=LogisticRegression(random_state=42))In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. StackingClassifier(estimators=[('dt',
DecisionTreeClassifier(criterion='entropy',
max_depth=4,
min_samples_leaf=0.008,
min_samples_split=0.008,
random_state=42,
splitter='random')),
('rl',
LogisticRegression(C=2.0,
class_weight={0: 1, 1: 2},
penalty='l1',
solver='liblinear',
tol=0.001)),
('rf',
RandomForestClassifier(max_depth=5,
min_samples_leaf=0.01,
min_samples_sp...
multi_strategy=None,
n_estimators=None, ...)),
('knn',
KNeighborsClassifier(metric='manhattan',
n_neighbors=15,
weights='distance')),
('mlp',
MLPClassifier(activation='tanh', alpha=0.05,
hidden_layer_sizes=(50, 50),
max_iter=1000, random_state=42)),
('svc',
SVC(C=0.1, gamma=0.1, kernel='linear',
probability=True))],
final_estimator=LogisticRegression(random_state=42))DecisionTreeClassifier(criterion='entropy', max_depth=4, min_samples_leaf=0.008,
min_samples_split=0.008, random_state=42,
splitter='random')LogisticRegression(C=2.0, class_weight={0: 1, 1: 2}, penalty='l1',
solver='liblinear', tol=0.001)RandomForestClassifier(max_depth=5, min_samples_leaf=0.01,
min_samples_split=0.01, n_estimators=50)GradientBoostingClassifier(learning_rate=0.01, max_depth=7, max_features='sqrt',
min_samples_split=4, random_state=42, subsample=0.8)LGBMClassifier(lambda_l1=0, lambda_l2=1, max_depth=2, min_data_in_leaf=5,
num_leaves=5, reg_alpha=0.1, verbose=-1)XGBClassifier(base_score=None, booster=None, callbacks=None,
colsample_bylevel=None, colsample_bynode=None,
colsample_bytree=0.7, device=None, early_stopping_rounds=None,
enable_categorical=False, eval_metric='mlogloss',
feature_types=None, gamma=None, grow_policy=None,
importance_type=None, interaction_constraints=None,
learning_rate=0.1, max_bin=None, max_cat_threshold=None,
max_cat_to_onehot=None, max_delta_step=None, max_depth=5,
max_leaves=None, min_child_weight=3, missing=nan,
monotone_constraints=None, multi_strategy=None, n_estimators=100,
n_jobs=None, num_parallel_tree=None, random_state=None, ...)XGBClassifier(base_score=None, booster=None, callbacks=None,
colsample_bylevel=None, colsample_bynode=None,
colsample_bytree=None, depth=6, device=None,
early_stopping_rounds=None, enable_categorical=False,
eval_metric='mlogloss', feature_types=None, gamma=None,
grow_policy=None, importance_type=None,
interaction_constraints=None, iterations=100, l2_leaf_reg=1,
learning_rate=0.1, max_bin=None, max_cat_threshold=None,
max_cat_to_onehot=None, max_delta_step=None, max_depth=None,
max_leaves=None, min_child_weight=None, missing=nan,
monotone_constraints=None, multi_strategy=None, n_estimators=None, ...)KNeighborsClassifier(metric='manhattan', n_neighbors=15, weights='distance')
MLPClassifier(activation='tanh', alpha=0.05, hidden_layer_sizes=(50, 50),
max_iter=1000, random_state=42)SVC(C=0.1, gamma=0.1, kernel='linear', probability=True)
LogisticRegression(random_state=42)
avaliar_modelo(X_train, y_train, X_test, y_test, stacking_model,nm_modelo='Stacking')
O blending de modelos é uma técnica de ensemble similar ao stacking, onde diferentes modelos de aprendizado de máquina são combinados para criar um
modelo composto mais robusto e preciso.
A diferença principal entre o blending e o stacking é a forma como as previsões dos modelos individuais são combinadas.
No blending, ao invés de usar um meta-modelo para aprender a melhor forma de combinar as previsões, as previsões dos modelos individuais são combinadas
de maneira mais simples, geralmente através de médias ponderadas, votações majoritárias ou outras técnicas de agregação.
Por exemplo, em um problema de regressão, o resultado final do blending pode ser a média ponderada das previsões dos modelos individuais, onde os pesos são
determinados com base no desempenho de validação de cada modelo.
Já em problemas de classificação, pode-se utilizar a moda ou a média das probabilidades preditas.
O blending é uma técnica menos flexível que o stacking, pois não permite que o modelo aprenda interações complexas entre as previsões dos modelos individuais,
mas pode ser mais simples e menos propenso a overfitting, dependendo do contexto.
No contexto do blending de modelos, as equações para combinar modelos em tarefas de regressão e classificação são geralmente bastante simples, dependendo principalmente
de como você escolhe combinar as previsões dos modelos individuais.
1. Para Regressão:
Modelos Individuais: Suponha que temos $ M $ modelos individuais, e cada modelo $ m_i $ faz uma previsão $ \hat{y}_i $ para uma instância $ x $.
Blending:
No blending, você pode combinar as previsões dos modelos individuais usando, por exemplo, uma média (possivelmente ponderada):
Onde $ w_i $ são pesos que somam 1 e podem ser atribuídos com base no desempenho de validação de cada modelo.
2. Para Classificação:
Modelos Individuais:
Cada modelo $ m_i $ produzirá uma probabilidade $ p_i $ da instância $ x $ pertencer à classe positiva.
Blending:
Para classificação, o blending pode envolver o cálculo da média das probabilidades preditas (ou votação majoritária em caso de classificações diretas):
E a classe final prevista pode ser determinada com base em um limiar, como 0.5 em problemas binários:
Nota:
Os pesos $ w_i $ podem ser definidos com base no desempenho dos modelos em um conjunto de validação, e a escolha do método de blending (média, média ponderada,
votação majoritária, etc.) dependerá do problema específico e do contexto em que os modelos estão sendo aplicados.
from sklearn.metrics import accuracy_score
import numpy as np
%%time
# Obter as probabilidades preditas pelos modelos treinados: MLP e Random Forest
probas_model1 = best_model_rf.predict_proba(X_test)
probas_model2 = best_model_mlp.predict_proba(X_test)
# Definir os pesos para os modelos
weights = [0.6, 0.4]
# Calcular a média ponderada das probabilidades
blended_probas = weights[0] * probas_model1 + weights[1] * probas_model2
# Determinar as classes preditas com base nas probabilidades combinadas
blended_predictions = np.argmax(blended_probas, axis=1)
# Avaliar o modelo combinado no conjunto de teste
score = accuracy_score(y_test, blended_predictions)
print(f'Blended Model Accuracy: {score:.2f}')
Blended Model Accuracy: 0.79 CPU times: total: 78.1 ms Wall time: 36 ms
from sklearn.metrics import roc_curve, auc, confusion_matrix, roc_auc_score
from sklearn.preprocessing import label_binarize
import matplotlib.pyplot as plt
from scipy import interp<>from itertools import cycle
# Função para calcular Gini
def gini_index(auc_score):
return 2 * auc_score - 1
# Calcular as probabilidades, previsões e métricas para treino e teste
for dataset_name, X, y in zip(['Train', 'Test'], [X_train, X_test], [y_train, y_test]):
# Obter as probabilidades preditas pelos modelos
probas_model1 = best_model_rf.predict_proba(X)
probas_model2 = best_model_mlp.predict_proba(X)
# Calcular a média ponderada das probabilidades
blended_probas = weights[0] * probas_model1 + weights[1] * probas_model2
# Determinar as classes preditas com base nas probabilidades combinadas
blended_predictions = np.argmax(blended_probas, axis=1)
# Calcular o AUC-ROC e Gini
y_bin = label_binarize(y, classes=np.unique(y))
if y_bin.shape[1] == 1:
y_bin = np.hstack((1 - y_bin, y_bin))
fpr = dict()
tpr = dict()
roc_auc = dict()
for i in range(y_bin.shape[1]):
fpr[i], tpr[i], _ = roc_curve(y_bin[:, i], blended_probas[:, i])
roc_auc[i] = auc(fpr[i], tpr[i])
# Calcular o micro-average ROC curve e ROC area
fpr["micro"], tpr["micro"], _ = roc_curve(y_bin.ravel(), blended_probas.ravel())
roc_auc["micro"] = auc(fpr["micro"], tpr["micro"])
# Calcular a matriz de confusão
cm = confusion_matrix(y, blended_predictions)
# Exibir as métricas
print(f'{dataset_name} Set:')
print('Confusion Matrix:')
print(cm)
print('ROC-AUC Scores per Class:', roc_auc)
print('Gini Indexes per Class:', {k: gini_index(v) for k, v in roc_auc.items()})
print()
# Plotar a curva ROC para cada classe
plt.figure(figsize=(10, 8))
lw = 2
colors = cycle(['aqua', 'darkorange', 'cornflowerblue'])
for i, color in zip(range(y_bin.shape[1]), colors):
plt.plot(fpr[i], tpr[i], color=color, lw=lw,
label=f'ROC curve of class {i} (area = {roc_auc[i]:0.2f})')
plt.plot([0, 1], [0, 1], 'k--', lw=lw)
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title(f'Receiver Operating Characteristic - {dataset_name} Set')
plt.legend(loc="lower right")
plt.show()
Train Set:
Confusion Matrix:
[[367 25]
[ 73 158]]
ROC-AUC Scores per Class: {0: 0.9019182348263981, 1: 0.9019182348263981, 'micro': 0.9139796304836794}
Gini Indexes per Class: {0: 0.8038364696527962, 1: 0.8038364696527962, 'micro': 0.8279592609673587}
Test Set:
Confusion Matrix:
[[143 14]
[ 41 70]]
ROC-AUC Scores per Class: {0: 0.8666437137774717, 1: 0.8666437137774716, 'micro': 0.8745126977055022}
Gini Indexes per Class: {0: 0.7332874275549435, 1: 0.7332874275549432, 'micro': 0.7490253954110044}
# Supondo que best_model_gbm seja o seu modelo treinado
with open('best_model_dt.pkl', 'wb') as file:
pickle.dump(best_model_dt, file)
with open('best_model_rl.pkl', 'wb') as file:
pickle.dump(best_model_gbm, file)
with open('best_model_rf.pkl', 'wb') as file:
pickle.dump(best_model_gbm, file)
with open('best_model_gbm.pkl', 'wb') as file:
pickle.dump(best_model_gbm, file)
with open('best_model_lightgbm.pkl', 'wb') as file:
pickle.dump(best_model_lightgbm, file)
with open('best_model_xgbm.pkl', 'wb') as file:
pickle.dump(best_model_lightgbm, file)
with open('best_model_catbst.pkl', 'wb') as file:
pickle.dump(best_model_catbst, file)
with open('best_model_knn.pkl', 'wb') as file:
pickle.dump(best_model_knn, file)
with open('best_model_mlp.pkl', 'wb') as file:
pickle.dump(best_model_knn, file)
with open('best_model_svm.pkl', 'wb') as file:
pickle.dump(best_model_svm, file)
# Lendo os modelos treinados
with open('best_model_rl.pkl', 'rb') as file:
loaded_model_rl = pickle.load(file)
with open('best_model_rf.pkl', 'rb') as file:
loaded_model_rf = pickle.load(file)
with open('best_model_gbm.pkl', 'rb') as file:
loaded_model_gbm = pickle.load(file)
with open('best_model_lightgbm.pkl', 'rb') as file:
loaded_model_lightgbm = pickle.load(file)
with open('best_model_xgbm.pkl', 'rb') as file:
loaded_model_xgbm = pickle.load(file)
with open('best_model_catbst.pkl', 'rb') as file:
loaded_model_catbst = pickle.load(file)
with open('best_model_knn.pkl', 'rb') as file:
loaded_model_knn = pickle.load(file)
with open('best_model_mlp.pkl', 'rb') as file:
loaded_model_mlp = pickle.load(file)
with open('best_model_svm.pkl', 'rb') as file:
loaded_model_svm = pickle.load(file)
loaded_model_gbm
GradientBoostingClassifier(learning_rate=0.01, max_depth=7, max_features='sqrt',
min_samples_split=4, random_state=42, subsample=0.8)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. GradientBoostingClassifier(learning_rate=0.01, max_depth=7, max_features='sqrt',
min_samples_split=4, random_state=42, subsample=0.8)import pandas as pd
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score
def evaluate_models(X_train, y_train, X_test, y_test, models):
metrics = []
for name, model in models.items():
# Prever os rótulos para os conjuntos de treino e teste
train_preds = model.predict(X_train)
test_preds = model.predict(X_test)
# Calcular as métricas
accuracy = accuracy_score(y_test, test_preds)
precision = precision_score(y_test, test_preds)
recall = recall_score(y_test, test_preds)
f1 = f1_score(y_test, test_preds)
auc = roc_auc_score(y_test, model.predict_proba(X_test)[:, 1]) # Supondo que é um problema de classificação binária
Gini = 2*auc - 1
# Adicionar ao array de métricas
metrics.append({
'Model': name,
# 'Train Accuracy': accuracy_score(y_train, train_preds),
'Accuracy': accuracy,
'Precision': precision,
'Recall': recall,
'F1 Score': f1,
'AUC-ROC': auc,
'Gini':Gini
})
# Converter o array de métricas em um DataFrame
metrics_df = pd.DataFrame(metrics)
# Ordenar o DataFrame pela metrica Gini
metrics_df_sorted = metrics_df.sort_values(by='Gini',ascending=False)
# Função para destacar o maior valor em azul claro
def highlight_max(s):
is_max = s == s.max()
return ['background-color: lightblue' if v else '' for v in is_max]
# Aplicando o estilo na coluna 'A'
metrics_df_sorted = metrics_df_sorted.style.apply(highlight_max, subset=['Gini'])
return metrics_df_sorted
# Supondo que loaded_model_gbm seja o modelo carregado
models = {'Regressão Logística': loaded_model_rl,
'Random Forest': loaded_model_rf,
'Gradient Boosting': loaded_model_gbm,
'LightGBM': loaded_model_lightgbm,
'XGBoost': loaded_model_xgbm,
'CatBoost': loaded_model_catbst,
'KNN': loaded_model_knn,
'Redes Neurais - MLP': loaded_model_mlp,
'SVM': loaded_model_svm,
}
# Chamar a função com os datasets de treino e teste e os modelos carregados
metrics_df = evaluate_models(X_train, y_train, X_test, y_test, models)
metrics_df
| Model | Accuracy | Precision | Recall | F1 Score | AUC-ROC | Gini | |
|---|---|---|---|---|---|---|---|
| 8 | SVM | 0.791045 | 0.772277 | 0.702703 | 0.735849 | 0.889482 | 0.778964 |
| 0 | Regressão Logística | 0.820896 | 0.888889 | 0.648649 | 0.750000 | 0.867906 | 0.735812 |
| 1 | Random Forest | 0.820896 | 0.888889 | 0.648649 | 0.750000 | 0.867906 | 0.735812 |
| 2 | Gradient Boosting | 0.820896 | 0.888889 | 0.648649 | 0.750000 | 0.867906 | 0.735812 |
| 3 | LightGBM | 0.809701 | 0.865854 | 0.639640 | 0.735751 | 0.866099 | 0.732197 |
| 4 | XGBoost | 0.809701 | 0.865854 | 0.639640 | 0.735751 | 0.866099 | 0.732197 |
| 5 | CatBoost | 0.802239 | 0.802083 | 0.693694 | 0.743961 | 0.843490 | 0.686980 |
| 6 | KNN | 0.735075 | 0.738095 | 0.558559 | 0.635897 | 0.777529 | 0.555058 |
| 7 | Redes Neurais - MLP | 0.735075 | 0.738095 | 0.558559 | 0.635897 | 0.777529 | 0.555058 |
%reload_ext watermark
%watermark -a "Roberto Soares - LfLngLrnng"
Author: Roberto Soares - LfLngLrnng
%watermark -v -m
Python implementation: CPython Python version : 3.11.9 IPython version : 8.25.0 Compiler : MSC v.1916 64 bit (AMD64) OS : Windows Release : 10 Machine : AMD64 Processor : Intel64 Family 6 Model 158 Stepping 9, GenuineIntel CPU cores : 4 Architecture: 64bit
%watermark --iversions
matplotlib: 3.8.4 numpy : 1.26.4 pandas : 2.2.2 xgboost : 2.0.3 lightgbm : 4.3.0
Fim
!jupyter nbconvert --to html --template=D:/anaconda3/envs/spark-pod-env/share/jupyter/nbconvert/templates/compatibility/mytemplate_a.tpl A013_Problemas_de_Classificacao_Algoritmos.ipynb
[NbConvertApp] Converting notebook A013_Problemas_de_Classificacao_Algoritmos.ipynb to html [NbConvertApp] Writing 9909193 bytes to A013_Problemas_de_Classificacao_Algoritmos.html